//package com.allwees.core.dao.autoupdate.impl;
//
//import java.beans.PropertyDescriptor;
//import java.lang.reflect.Field;
//import java.lang.reflect.Method;
//import java.math.BigDecimal;
//import java.util.Date;
//import java.util.Set;
//
//import javax.annotation.PostConstruct;
//import javax.persistence.Column;
//import javax.persistence.Id;
//import javax.persistence.Table;
//import javax.persistence.Temporal;
//import javax.persistence.Transient;
//import javax.sql.DataSource;
//
//import org.apache.commons.beanutils.PropertyUtils;
//import org.apache.commons.lang3.RandomStringUtils;
//import org.apache.commons.lang3.StringUtils;
//import org.apache.ibatis.javassist.Modifier;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.beans.factory.annotation.Value;
//import org.springframework.stereotype.Service;
//
//import com.alibaba.druid.pool.DruidDataSource;
//import com.baomidou.mybatisplus.annotation.TableField;
//import com.baomidou.mybatisplus.annotation.TableId;
//import com.baomidou.mybatisplus.annotation.TableName;
//import com.baomidou.mybatisplus.core.enums.IEnum;
//
//import com.allwees.core.common.util.StringUtil;
//import com.allwees.core.common.util.reflect.ReflectionUtils;
//import com.allwees.core.dao.autoupdate.AutoUpdateTableService;
//import com.allwees.core.dao.jdbc.JdbcDao;
//import com.allwees.core.dao.jdbc.impl.JdbcDaoImpl;
//
//import cn.hutool.core.util.ClassUtil;
//import lombok.extern.slf4j.Slf4j;
//
///**
// * 根据Entity定义自动更新数据库表结构（仅支持单个数据源）
// *
// * @author yangylsky
// *
// */
//@Slf4j
//@Service
//public class AutoUpdateTableServiceImpl implements AutoUpdateTableService {
//	@Autowired
//	private DataSource dataSource;
//
//    @Value("${generator.auto-update:false}")
//	private boolean autoUpdate;
//
//	private JdbcDao jdbcDao;
//
//	private String dbName;
//
//	@PostConstruct
//	private void init() {
//		if(!autoUpdate) {
//			return;
//		}
//		jdbcDao = new JdbcDaoImpl(dataSource);
//		dbName = parseDbName();
//		update();
//	}
//
//	@Override
//	public boolean update() {
//		Set<Class<?>> entityClasses = ClassUtil.scanPackageByAnnotation("com.allwees", TableName.class);
//		for(Class<?> entityClass : entityClasses) {
//			log.info("解析实体类:" + entityClass.getName());
//			try {
//				createTable(entityClass);
//				parserEntity(entityClass);
//			} catch(Exception e) {
//				log.error("error", e);
//			}
//		}
//		return true;
//	}
//
//	private void createTable(Class<?> entityClass) {
//		String tableName = getTableName(entityClass);
//		if(!tableExist(tableName)) {
//			String ddl = String.format("CREATE TABLE %s (id INT4 AUTO_INCREMENT PRIMARY KEY)", tableName);
//			jdbcDao.execute(ddl);
//			log.info(ddl);
//		}
//	}
//
//	private String getTableName(Class<?> entityClass) {
//		String tableName = "";
//		if(entityClass.isAnnotationPresent(TableName.class)) {
//			tableName = entityClass.getAnnotation(TableName.class).value();
//		} else if(entityClass.isAnnotationPresent(Table.class)) {
//			tableName = entityClass.getAnnotation(Table.class).name();
//		}
//		if(StringUtils.isBlank(tableName)) {
//			tableName = StringUtil.humpToSeparate(entityClass.getSimpleName());
//		}
//		return tableName;
//	}
//
//	private boolean tableExist(String tableName) {
//		String sql = "select count(1) from information_schema.tables where table_schema=? and table_name=?";
//		int tableCount = jdbcDao.queryForBaseType(Integer.class, sql, dbName, tableName);
//		return tableCount > 0;
//	}
//
//	private boolean columnExist(String tableName, String columnName) {
//		String sql = "select count(1) from information_schema.columns where table_schema=? and table_name=? and column_name=?";
//		int columnCount = jdbcDao.queryForBaseType(Integer.class, sql, dbName, tableName, columnName);
//		return columnCount > 0;
//	}
//
//	private void parserEntity(Class<?> entityClass) {
//		PropertyDescriptor[] props = PropertyUtils.getPropertyDescriptors(entityClass);
//		for(PropertyDescriptor prop : props) {
//			createColumn(entityClass, prop.getName());
//		}
//	}
//
//	/**
//	 * 根据指定Entity的fieldName创建Column
//	 *
//	 * @param entityClass
//	 * @param fieldName
//	 */
//	private void createColumn(Class<?> entityClass, String fieldName) {
//		Field field = ReflectionUtils.getField(entityClass, fieldName);
//		if(field != null) {
//			createColumn(getTableName(entityClass), field);
//		}
//	}
//
//	private void createColumn(String tableName, Field entityField) {
//		if(Modifier.isTransient(entityField.getModifiers())  // transient 修饰
//				|| Modifier.isStatic(entityField.getModifiers())  // static 修饰
//				|| entityField.isAnnotationPresent(Transient.class)) { // @Transient 修饰
//			return;
//		}
//		if(entityField.isAnnotationPresent(TableField.class)) { // 解析mybatisplus注解
//			TableField tableField = entityField.getAnnotation(TableField.class);
//			if(!tableField.exist()) {
//				return;
//			}
//		}
//		String columnName = getColumnName(entityField);
//		if(columnExist(tableName, columnName)) {
//			return;
//		}
//		String typeDef = getColumnTypeDef(entityField);
//		if(typeDef == null) {
//			return;
//		}
//		String ddl = String.format("ALTER TABLE %s ADD COLUMN %s %s;", tableName, columnName, typeDef);
//		jdbcDao.execute(ddl);
//		log.info(ddl);
//		addUniqueConstraint(tableName, entityField);
//		addIndex(tableName, entityField);
//	}
//
//	/**
//	 * 根据Column注解增加唯一键约束
//	 *
//	 * @param tableName
//	 * @param entityField
//	 */
//	private void addUniqueConstraint(String tableName, Field entityField) {
//		Column columnDesc = entityField.getAnnotation(Column.class);
//		if(columnDesc != null) {
//			if(columnDesc.unique()) {
//				String ukName = "uk_" + tableName + "_" + entityField.getName();
//				String ddl = String
//						.format("ALTER TABLE %s ADD CONSTRAINT %s UNIQUE (%s);", tableName, ukName, getColumnName(entityField));
//				jdbcDao.execute(ddl);
//				log.info(ddl);
//			}
//		}
//	}
//
//	/**
//	 * 根据Index注解创建索引
//	 *
//	 * @param tableName
//	 * @param entityField
//	 */
//	private void addIndex(String tableName, Field entityField) {
//		Index indexDesc = entityField.getAnnotation(Index.class);
//		if(indexDesc != null) {
//			String indexName = indexDesc.name();
//			if(StringUtils.isBlank(indexName)) {
//				indexName = "idx_" + RandomStringUtils.randomAlphanumeric(16, 20);
//			}
//			String ddl = String.format("CREATE %s INDEX %s ON %s (%s);", (indexDesc.unique() ? "UNIQUE" : ""), indexName, tableName, getColumnName(entityField));
//			jdbcDao.execute(ddl);
//			log.info(ddl);
//		}
//	}
//
//	private String getColumnName(Field entityField) {
//		String columnName = toDbField(entityField.getName());
//		if(entityField.isAnnotationPresent(Column.class)) {
//			Column column = entityField.getAnnotation(Column.class);
//			columnName = StringUtils.isNotBlank(column.name()) ? column.name() : columnName;
//		}
//		return columnName;
//	}
//
//	private String getColumnTypeDef(Field entityField) {
//		String typeDef = null;
//		Class<?> typeClazz = entityField.getType();
//		String typeName = typeClazz.getName();
//		boolean isPrimaryKey = entityField.isAnnotationPresent(Id.class) || entityField.isAnnotationPresent(TableId.class);
//
//		//处理主键
//		if(isPrimaryKey) {
//			if(String.class.equals(typeClazz)) {
//				return " VARCHAR(48) PRIMARY KEY";
//			} else if("long".equals(typeName) || Long.class.equals(typeClazz)) {
//				return " INT8 PRIMARY KEY";
//			} else if("int".equals(typeName) || Integer.class.equals(typeClazz)) {
//				return " INT4 PRIMARY KEY";
//			} else {
//				throw new RuntimeException("不支持的主键类型[" + typeName + "]");
//			}
//		}
//		//处理Enum字段（如果是mybatisplus，字段的type class需要实现IEnum接口，或者type class里的字段附带EnumValue注解）
//		if(typeClazz.isEnum()) {
//			if(IEnum.class.isAssignableFrom(typeClazz)) {
//				Method method = ReflectionUtils.getMethod(typeClazz, "getValue");
//				if(method != null) {
//					Class<?> columnDefType = method.getReturnType();
//					if(String.class.equals(columnDefType)) {
//						typeDef = "VARCHAR(48)";
//					} else if(Number.class.isAssignableFrom(columnDefType)) {
//						typeDef = "int2";
//					}
//				}
//			} else {
//				//TODO - 处理EnumValue注解
//			}
//		}
//		//处理自定义columnDefinition
//		Column columnDesc = entityField.getAnnotation(Column.class);
//		if(columnDesc != null && StringUtils.isNotBlank(columnDesc.columnDefinition())) {
//			typeDef = columnDesc.columnDefinition();
//		}
//		if(StringUtils.isBlank(typeDef)) {
//			//处理普通字段
//			if("int".equals(typeName) || Integer.class.equals(typeClazz)) {
//				typeDef = "int4";
//			} else if("long".equals(typeName) || Long.class.equals(typeClazz)) {
//				typeDef = "int8";
//			} else if("float".equals(typeName) || Float.class.equals(typeClazz)) {
//				typeDef = "float4";
//			} else if("double".equals(typeName) || Double.class.equals(typeClazz)) {
//				typeDef = "float8";
//			} else if("boolean".equals(typeName) || Boolean.class.equals(typeClazz)) {
//				typeDef = "bool";
//			} else if(String.class.equals(typeClazz)) {
//				int length = 255;
//				if(columnDesc != null) {
//					length = columnDesc.length();
//				}
//				if(length <= 8192) { //8K字符内使用VARCHAR
//					typeDef = "VARCHAR(" + length + ")";
//				} else if(8192 < length && length < 65535) {
//					typeDef = "text";
//				} else if(65535 <= length) {
//					typeDef = "mediumtext";
//				}
//			} else if(Date.class.isAssignableFrom(typeClazz)) {
//				Temporal temporal = entityField.getAnnotation(Temporal.class);
//				typeDef = (temporal == null) ? "datetime" : temporal.value().name().toLowerCase();
//			} else if(BigDecimal.class.equals(typeClazz)) {
//				int precision = 13;
//				int scale = 2;
//				if(columnDesc != null) {
//					precision = columnDesc.precision() > 0 ? columnDesc.precision() : precision;
//					scale = columnDesc.scale();
//				}
//				typeDef = "numeric(" + precision + "," + scale + ")";
//			}
//		}
//		if(columnDesc != null) {
//			if(!columnDesc.nullable()) {
//				typeDef += " not null";
//			}
//			if(columnDesc.unique()) {
//				typeDef += " unique";
//			}
//		}
//		return typeDef;
//	}
//
//	private String parseDbName() {
//		if(!(dataSource instanceof DruidDataSource)) {
//			throw new RuntimeException("目前只支持从DruidDataSource获取jdbc信息并建立连接");
//		}
//		String dbUrl = ((DruidDataSource) dataSource).getUrl();
//		if(dbUrl.contains("?")) {
//			dbUrl = StringUtils.substringBefore(dbUrl, "?");
//		}
//		return dbUrl.substring(dbUrl.lastIndexOf("/") + 1);
//	}
//
//	private String toDbField(String filedName){
//		return StringUtil.humpToSeparate(filedName);
//	}
//
//	public void setAutoUpdate(Boolean autoUpdate) {
//		this.autoUpdate = autoUpdate == null ? false : autoUpdate;
//	}
//}
